
/**
 * 位数组
 */
export class Bits {

    readonly bits: number[] = [];
    protected _dirty = true;

    /**
     * 重置为0
     */
    reset() {
        this.bits.length = 0;
        return this;
    }

    /**
     * 获取bits某一位上的值 0|1
     * @param idx 
     */
    getBit(idx: number) {
        if (idx < 0) {
            return 0;
        }
        if (idx <= 32) {
            const val = this.bits[0];
            if (val) {
                return (val & 1 << idx) ? 1 : 0;
            }
        }
        const arrIdx = idx / 32 >>> 0;
        const val = this.bits[arrIdx];
        if (val) {
            return (val & 1 << (idx % 32)) ? 1 : 0;
        }
        return 0;
    }

    /**
     * 设置bits上某一位为1或0
     * @param idx 位
     * @param val true:1 false:0
     */
    setBit(idx: number, val: any) {
        if (idx < 0) {
            return this;
        }
        if (idx <= 32) {
            if (val) {
                if (this.bits[0] === undefined) {
                    this.bits[0] = 1 << (idx % 32);
                } else {
                    this.bits[0] |= 1 << (idx % 32);
                }
                this._dirty = true;
            } else if (this.bits[0]) {
                this.bits[0] &= ~(1 << (idx % 32));
                this._dirty = true;
            }
            return this;
        }

        const arrIdx = idx <= 32 ? 0 : (idx / 32 >>> 0);
        if (val) {
            if (this.bits[arrIdx] === undefined) {
                this.bits[arrIdx] = 1 << (idx % 32);
            } else {
                this.bits[arrIdx] |= 1 << (idx % 32);
            }
            this._dirty = true;
        } else if (this.bits[arrIdx]) {
            this.bits[arrIdx] &= ~(1 << (idx % 32));
            this._dirty = true;
        }
        return this;
    }

    /**
     * 获取第几个bits的值
     * @param idx 
     */
    getBits(idx: number) {
        return this.bits[idx] || 0;
    }

    /**
     * 设置第几个bits的值
     * @param idx 
     * @param val 
     */
    setBits(idx: number, val: number) {
        this.bits[idx] = val;
        return this;
    }

    /**
     * &运算后 其中一位为1则返回true
     * @param bits 
     */
    checkHasOne(bits: Bits) {
        if (this.bits.length === 1) {
            if ((this.getBits(0) & bits.getBits(0)) > 0) {
                return true;
            }
        } else {
            for (let i = 0; i < this.bits.length; i++) {
                if ((this.getBits(i) & bits.getBits(i)) > 0) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * &运算后 每一位都为1则返回true
     * @param bits 
     */
    checkHasAll(bits: Bits) {
        if (this.bits.length === 1 && bits.bits.length === 1) {
            if ((this.getBits(0) & bits.getBits(0)) !== this.getBits(0)) {
                return false;
            }
        } else {
            const len = Math.max(this.bits.length, bits.bits.length);
            for (let i = 0; i < len; i++) {
                if ((this.getBits(i) & bits.getBits(i)) !== this.getBits(i)) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 转化成 bits1-bits2-bits3-bits4 格式的字符串 
     * @param 进制
     */
    toString(radix = 2) {
        let key = "";
        if (this.bits.length > 0) {
            const len = this.bits.length - 1;
            for (let i = 0; i < len; ++i) {
                key += (this.bits[i]?.toString(radix) || "0") + "-";
            }
            key += (this.bits[(this.bits.length - 1)]?.toString(radix) || "0");
        }
        return key;
    }

}